/**
********************************************************
*
* @file      Hal_temp_hum.c
* @author    Gizwtis
* @version   V03010100
* @date      2016-07-05
*
* @brief     机智云.只为智能硬件而生
*            Gizwits Smart Cloud  for Smart Products
*            链接|增值ֵ|开放|中立|安全|自有|自由|生态
*            www.gizwits.com
*
*********************************************************/
#include "hal_temp_hum.h"
#include <string.h>
#include "delay.h"

thTypedef_t temphumTypedef;


//Reset DHT11
static void dht11Rst(void)
{
    DHT11_IO_OUT(); 			            //SET OUTPUT
    DHT11_DQ_OUT=0; 			            //GPIOA.0=0
    delayUs(500);    			            //Pull down Least 18ms
    DHT11_DQ_OUT=1; 			            //GPIOA.0=1
    delayUs(30);     			            //Pull up 20~40us
}

static uint8_t dht11Check(void)
{
    uint8_t retry=0;
    DHT11_IO_IN();                                              //SET INPUT
    while (DHT11_DQ_IN && (retry<100))                          //DHT11 Pull down 40~80us
    {
        retry++;
        delayUs(1);
    }

    if(retry >= 100)
    {
        return 1;
    }
    else
    {
        retry=0;
    }

    while (!DHT11_DQ_IN&& (retry < 100))		    //DHT11 Pull up 40~80us
    {
        retry++;
        delayUs(1);
    }

    if(retry >= 100)
    {
        return 1;	                        //check error
    }        

    return 0;
}

static uint8_t dht11ReadBit(void)
{
    uint8_t retry=0;
    while(DHT11_DQ_IN && (retry<100))                           //wait become Low level
    {
        retry++;
        delayUs(1);
    }

    retry = 0;
    while(!DHT11_DQ_IN && (retry < 100))		    //wait become High level
    {
        retry++;
        delayUs(1);
    }

    delayUs(30);//wait 40us

    if(DHT11_DQ_IN)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

static uint8_t dht11ReadByte(void)
{
    uint8_t i,dat;
    dat=0;
    for (i=0; i<8; i++)
    {
        dat<<=1;
        dat |= dht11ReadBit();
    }

    return dat;
}

static uint8_t dht11ReadData(uint8_t *tempint,uint8_t *tempdec,uint8_t *humint,uint8_t *humdec)
{
    uint8_t buf[5];
    uint8_t i;
    dht11Rst(); 
    if(0 == dht11Check()) 
    {
        for(i=0; i<5; i++)
        {
            buf[i] = dht11ReadByte();
        }
				printf("raw data: %02x %02x %02x %02x %02x\n",
					buf[0],buf[1],buf[2],buf[3],buf[4]);

				int sum = (buf[0]+buf[1]+buf[2]+buf[3])&0xff;
				if(sum != buf[4])
				{
					printf("check sum error %d\n",sum);
				}
				else
				{
					int hum = ((buf[0]<<8)|buf[1]);
					int tmp = ((buf[2]<<8)|buf[3]);
					
					*tempint = tmp/10;
					*tempdec = tmp%10;
					*humint = hum/10;
					*humdec = hum%10;
				}
    }
    else
    {
        return 1;
    }

    return 0;
}

uint8_t dht11Read(uint8_t *tempint,uint8_t *tempdec,uint8_t *humint,uint8_t *humdec)
{
    uint8_t curTemInt = 0, curHumInt = 0;
		uint8_t curTemDec = 0, curHumDec = 0;
    uint8_t curI = 0;
    uint8_t ret = 0; 
		uint16_t temMeans = 0, humMeans = 0;

    ret = dht11ReadData(&curTemInt,&curTemDec,&curHumInt,&curHumDec);

		//printf("tmp %d.%d hum %d.%d\n",*curTemInt,*curTemDec,*curHumInt,*curHumDec);
		if(1 != ret) 
		{
				//Cycle store ten times stronghold
				if(MEAN_NUM > temphumTypedef.curI)
				{
						temphumTypedef.thBufs[temphumTypedef.curI][0] = curTemInt*10+curTemDec;
						temphumTypedef.thBufs[temphumTypedef.curI][1] = curHumInt*10+curHumDec;

						temphumTypedef.curI++;
				}
				else
				{
						temphumTypedef.curI = 0;

						temphumTypedef.thBufs[temphumTypedef.curI][0] = curTemInt*10+curTemDec;
						temphumTypedef.thBufs[temphumTypedef.curI][1] = curHumInt*10+curHumDec;

						temphumTypedef.curI++;
				}
		}
		else
		{
				return (1); 
		}
		
		if(MEAN_NUM <= temphumTypedef.curI) 
		{
				temphumTypedef.thAmount = MEAN_NUM;
		}

		if(0 == temphumTypedef.thAmount) 
		{
				//Calculate Before ten the mean
				for(curI = 0; curI < temphumTypedef.curI; curI++)
				{
						temMeans += temphumTypedef.thBufs[curI][0];
						humMeans += temphumTypedef.thBufs[curI][1];
				}

				temMeans = temMeans / temphumTypedef.curI;
				humMeans = humMeans / temphumTypedef.curI;
				
				*tempint = (uint8_t)(temMeans/10);
				*tempdec = (uint8_t)(temMeans%10);
				*humint = (uint8_t)(humMeans/10);
				*humdec = (uint8_t)(humMeans%10);
		}
		else if(MEAN_NUM == temphumTypedef.thAmount) 
		{
				//Calculate After ten times the mean
				for(curI = 0; curI < temphumTypedef.thAmount; curI++) 
				{
						temMeans += temphumTypedef.thBufs[curI][0];
						humMeans += temphumTypedef.thBufs[curI][1];
				}

				temMeans = temMeans / temphumTypedef.thAmount; 
				humMeans = humMeans / temphumTypedef.thAmount; 
				
				*tempint = (uint8_t)(temMeans/10);
				*tempdec = (uint8_t)(temMeans%10);
				*humint = (uint8_t)(humMeans/10);
				*humdec = (uint8_t)(humMeans%10);
		}

		printf("tmp %d.%d hum %d.%d\n",*tempint,*tempdec,*humint,*humdec);
		
    return (0);
}

uint8_t dht11Init(void)
{
    /* Migrate your driver code */
    GPIO_InitTypeDef  GPIO_InitStructure;

    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    //GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);

    GPIO_InitStructure.Pin = GPIO_PIN_3;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
    //HAL_GPIO_SetBits(GPIOB,GPIO_Pin_3);

    dht11Rst(); 
    
    memset((uint8_t *)&temphumTypedef, 0, sizeof(thTypedef_t)); 
    
    return dht11Check(); 
}
